home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / gc / INCLUDE / xr / GC.h next >
C/C++ Source or Header  |  1991-06-06  |  24KB  |  654 lines

  1. /* begincopyright
  2.   Copyright (c) 1988,1990 Xerox Corporation. All rights reserved.
  3.   Use and copying of this software and preparation of derivative works based
  4.   upon this software are permitted. Any distribution of this software or
  5.   derivative works must comply with all applicable United States export
  6.   control laws. This software is made available AS IS, and Xerox Corporation
  7.   makes no warranty about the software, its performance or its conformity to
  8.   any specification. Any person obtaining a copy of this software is requested
  9.   to send their name and post office or electronic mail address to:
  10.     PCR Coordinator
  11.     Xerox PARC
  12.     3333 Coyote Hill Rd.
  13.     Palo Alto, CA 94304
  14.     
  15.   Parts of this software were derived from code bearing the copyright notice:
  16.   
  17.   Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  18.   This material may be freely distributed, provided this notice is retained.
  19.   This material is provided as is, with no warranty expressed or implied.
  20.   Use at your own risk.
  21.   
  22.   endcopyright */
  23. /* 
  24.  * GC.h 
  25.  *
  26.  * Basic public type definitions for Xerox Runtime
  27.  *  storage managment package.
  28.  *
  29.  * Mark Weiser, October 18, 1989
  30.  * Alan Ishigo, November 14, 1988 4:38:01 pm PST
  31.  * Demers, October 24, 1989 1:58:02 pm PDT
  32.  * Boehm, July 19, 1990 1:18:27 pm PDT
  33.  *
  34.  */
  35.  
  36. #ifndef _XR_GC_
  37. #define _XR_GC_ 1
  38.  
  39. #ifndef _XR_BASIC_TYPES_
  40. #include "xr/BasicTypes.h"
  41. #endif
  42. /* The garbage collector used to assume sizeof (bool) = sizeof (long) */
  43. /* It may still.                              */
  44.  
  45. #ifndef _XR_THREADS_
  46. #include "xr/Threads.h"
  47. #endif
  48.  
  49. /* Public variables.  May be altered by client. */
  50. extern bool GC_dont_gc;      /* inhibit collection      */
  51. extern long GC_non_gc_bytes; /* Number of bytes declared to be uncollectable. */
  52. extern bool GC_markCarefully;
  53.                 /* Try to keep working set down during marking,  */
  54.             /* at the expense of about a factor of 2 in cpu  */
  55.             /* time.  Ignored during partial collections.     */
  56.             /* Setting or clearing this has only a transient */
  57.             /* effect, up to at least the next collection.   */
  58. extern bool GC_ok_to_panic; /* OK to call XR_panic if things go completely  */
  59.                 /* haywire.                        */
  60. extern unsigned GC_partial_gc_allocs;
  61.                        /* Number of words to be allocated between */
  62.                 /* partial collections.               */
  63.                 /* 0 ==> use default value based on number */
  64.                 /* of composite objects in use.            */
  65. extern unsigned GC_full_gc_allocs;
  66.                   /* Number of words to be allocated between   */
  67.                  /* full collections. 0 ==> collect only when */
  68.                  /* heap is full.                  */
  69.                  
  70. extern unsigned GC_free_mem_ratio;
  71.                  /* Collector tries to expand heap until       */
  72.                  /* 2*GC_composite_in_use/GC_free_mem_ratio    */
  73.                  /* words are reclaimed at full collections.   */
  74.                  /* Greater values imply smaller heaps, but       */
  75.                  /* risk excessive GC frequency.           */
  76.                  /* This is all very approximate.           */
  77.                  
  78. extern bool GC_fix_heap_size; /* Avoid expanding the heap if at all possible. */
  79.  
  80. /* Public variables.  Read only for the client.  Set by collector. */
  81. extern char * GC_heapstart;  /* A lower bound on all heap addresses */
  82.                       /* Known to be HBLKSIZE aligned.       */
  83.                       /* Zero before GC initialization.        */
  84.  
  85. extern char * GC_heaplim;   /* 1 + last address in heap */
  86.  
  87. extern long GC_heapsize;       /* Heap size in bytes */
  88.  
  89. extern char * GC_sys_mem_end; /* 1 + end of memory allocated from system.  */
  90.                   /* May differ from GC_heaplim if other       */
  91.                   /* allocation, e.g. for block headers       */
  92.                   /* is going on.                   */
  93.                
  94. extern long GC_mem_found;   /* Number of words reclaimed since start of last */
  95.                     /* collection.  Only a lower bound.                   */
  96.              
  97. extern long GC_mem_freed;  /* Number of longwords explicitly       */
  98.                    /* freed since last garbage collection. */
  99.              
  100. extern long GC_composite_in_use;  /* Number of longwords in accessible  */
  101.                       /* composite objects.                 */
  102.  
  103. extern long GC_atomic_in_use;     /* Number of longwords in accessible atomic */
  104.                       /* objects.                                 */
  105.                       /* Both of the above numbers are good upper */
  106.                       /* bounds, as of the last collection.       */
  107.                       
  108. extern long GC_objects_in_use;    /* Number of live objects found during last */
  109.                       /* collection.                      */
  110.                       
  111. extern bool GC_running_exclusive;  /* True if a single process has taken */
  112.                                     /* over all the processors. */
  113. extern bool GC_collection_in_progress;
  114.                   /* A parallel collection is currently      */
  115.                   /* running.  Changed to true only while    */
  116.                   /* GC_allocate_ml is held.                 */
  117.                   /* Currently not set during stop-the-world */
  118.                   /* collections.                 */         
  119.                
  120. extern char XR_gcVersion[]; /* read-only */
  121.                
  122.                
  123. /* Publically readable variables that may not remain meaningful           */
  124. /* if the collector changes.  Should be used only in disposable code.  */               
  125. extern long GC_markfaults;  /* The number of page faults that occurred during */
  126.                     /* the last mark phase.                           */    
  127.  
  128. extern GC_max_markfaults; /* The recent max of above */
  129.  
  130. extern long GC_gc_no;        /* How many times have we collected?    */
  131.  
  132. extern bool GC_full_gc;     /* A full collection is in progress     */
  133.                         
  134. extern bool GC_after_full;     /* Cleaning up a full GC     */
  135.  
  136. extern long GC_tenure_count;         /* Number of tenured blocks */
  137.  
  138. extern int GC_n_maps_cached;
  139.                /* The number of heap block maps currently in the cache */
  140.  
  141. extern int GC_words_at_full_gc;  /* Words accessible after last full     */
  142.                  /* collection.                */
  143.                  
  144. extern int GC_composite_at_full_gc;  /* Composite words accessible     */
  145.                      /* after last full collection.    */
  146.  
  147. /* The following are meaningful for any collector, but can only be       */
  148. /* maintained at significant expense, and may thus eventually disappear. */
  149. /* The object counts are more likely to disappear, since they are      */
  150. /* useless to the collector itself.                     */
  151.  
  152. extern unsigned GC_words_allocd;
  153.                      /* Number of words allocated since last collection */
  154.                  
  155. extern unsigned GC_words_allocd_before_gc;
  156.                     /* Words allocated up to last garbage   */
  157.                     /* collection.  The sum of this and the */
  158.                     /* preceding variable is the total      */
  159.                     /* number of words allocated since the  */
  160.                     /* beginning of the world.              */
  161.                 
  162. extern unsigned GC_objects_allocd;  /* Number of objects allocated since last */
  163.                     /* collection.                  */
  164.                     
  165. extern unsigned GC_objects_allocd_before_gc;
  166.                          /* Objects allocated up to last    */
  167.                     /* garbage collection.             */
  168.                  
  169.                  
  170. /* All routines in the GC interface start with either XR_ or GC_.  Internal */
  171. /* routines start with GC_.                            */
  172.  
  173. /***** Informational Routines *****/
  174.  
  175. extern unsigned
  176. XR_GCCurrentByteCount();
  177. /* Return the current number of bytes allocated.
  178.    This number increases continuously (at each allocation) but shrinks
  179.    only after collections. */
  180.  
  181. extern unsigned
  182. XR_GCCurrentObjectCount();
  183. /* Return the current number of objects allocated.
  184.    This number increases continuously (at each allocation) but shrinks
  185.    only after collections.
  186.    */
  187.  
  188. extern unsigned
  189. XR_GCTotalByteCount();
  190. /* Return the current number of bytes allocated.  This number increases
  191.    continuously.
  192.    */
  193.  
  194. extern unsigned
  195. XR_GCTotalObjectCount();
  196. /* Return the current number of bytes allocated.
  197.    This number increases continuously.
  198.    */
  199.  
  200. extern bool
  201. XR_NfreePagesP(/* unsigned N */);
  202. /*
  203.  * Returns 1 if at least N GC pages (i.e. hblocks) are free (no
  204.  * objects at all on them) and 0 otherwise.
  205.  * (Written this way, rather than just to return the number of free
  206.  * pages, to keep working set down by truncating search.)
  207.  */
  208.  
  209. /***** Routines to Control Behavior *****/
  210. /* The ...Set... routines always return the old value. */
  211.  
  212. extern bool
  213. XR_GCGetNeverCollectAtAll(), XR_GCSetNeverCollectAtAll(/* bool */);
  214. /* A value of TRUE causes no collection activity whatsoever.
  215.    A value of FALSE causes normal collection behavior (subject to the
  216.    NeverFree boolean).
  217.    */
  218.  
  219. extern unsigned
  220. XR_GCHeapSize();
  221. /* Returns the size of the heap in bytes. */
  222.  
  223. extern bool
  224. XR_Increase_Heap(/* unsigned */);
  225. /* The heap is grown by the indicated number of bytes, rounded up to
  226.    a pagesize.  Returns true if successful, false otherwise.
  227.    */
  228.  
  229. extern bool
  230. XR_GCSetMarkCarefully(/* bool */), XR_GCGetMarkCarefully( /* bool */);
  231. /* If this switch is set, then the objects to be marked are kept
  232.    sorted in page order so as to reduce paging behavior, at the obvious
  233.    cost of cpu time.  The switch is set by the collector after excessive
  234.    paging activity, and reset after a full collection with low paging
  235.    activity.
  236.    */
  237.  
  238. extern unsigned
  239. XR_GCSetMode(/* unsigned */);
  240. # define GC_INCREMENTAL 1
  241. # define GC_PARALLEL 2
  242. /* Turn on or off parallel and or incremental collection.  Default with */
  243. /* STICKY_MARK_BITS defined is both.  For batch processes it pays to    */
  244. /* turn off GC_PARALLEL.  For short-lived batch processes, and/or    */
  245. /* batch processes in small address spaces, it pays to turn both off.   */
  246. /* Turning both off will usually remove virtual dirty bit overhead.     */
  247.  
  248. unsigned
  249. XR_SetBytesAfterWhichToCollect(/* unsigned */), XR_GetBytesAfterWhichToCollect();
  250. /* A non-zero value causes a collection whenever this many bytes have
  251.    been allocated since the last collection.
  252.    */
  253.  
  254. void
  255. XR_CollectOnlyWhenFull(), XR_CollectAfterTwoMegabytes(), XR_CollectAfterOneMegabyte();
  256. /*
  257.   Convenient access to XR_SetBytesAfterWhichToCollect for folks
  258.   without access to arguments (e.g., via the 'pcr:' prompt.)
  259.   */
  260.  
  261. /***** Routines to cause behavior. *****/
  262. /* These routines are all monitored and safe to call at any time.
  263.    They are the basic interfaces into storage management.
  264.    */
  265.  
  266. void
  267. XR_GCollect();
  268. /* initiate a garbage collection. */
  269.  
  270. void
  271. XR_WaitForGC();
  272. /* Wait for a parallel collection to finish. (Implemented by acquiring and */
  273. /* releasing the trace monitor lock.)                       */
  274.  
  275.  
  276. /* general purpose allocation routines: */
  277.  
  278. XR_Pointer
  279. GC_malloc(/* unsigned ObjectSizeInBytes */);
  280. /* Allocates a new object of at least the specified length. The object is
  281.    cleared.  It will be aligned on at least a 4 byte boundary.  If the    
  282.    architecture requires n byte alignment for certain objects, then it will
  283.    be n byte aligned unless the requested size is less than n.  If the
  284.    requested size is a multiple of n, where n is a power of 2 no larger than
  285.    16, then the object will also be n byte aligned.  No space is implicitly
  286.    reserved for type tags or the like. Returns (XR_Pointer)0 if no memory
  287.    is available.
  288.    */
  289.    
  290. XR_Pointer
  291. GC_malloc_atomic(/* unsigned ObjectSizeInBytes */);
  292. /* Identical to GC_malloc, except that the object is assumed to contain no
  293.    pointers, amd the object is not cleared.  Is faster than, and results in
  294.    faster collections than GC_malloc.
  295.    */
  296.    
  297. XR_Pointer GC_realloc(/* XR_Pointer old_object, unsigned ObjectSizeInBytes */);
  298. /* Return a new object with indicated size, and contents of the old object.
  299.    The new object is assumed to not contain any pointers if the old object
  300.    was known not to contain pointers.  The new object is identical to the old
  301.    object whenever this can be easily arranged.  May be much faster than
  302.    a new allocation followed by a copy, but this probably happens only if the
  303.    client program uses a stupid algorithm.  Unfortunately, such clients are
  304.    common, at least in the C world.
  305.    */
  306.    
  307. void GC_free(/* XR_Pointer object */);
  308. /* Explicitly deallocate an object.  The object should have been allocated by
  309.    one of the above routines, NOT by one of those below. Results in disaster
  310.    if the object is subsequently accessed.
  311.    */
  312.    
  313. void XR_free(/* XR_Pointer p */);
  314. /* Similar to GC_free, but p may point to the interior of an object.  May */
  315. /* be used with any allocated object.                      */
  316.  
  317. XR_Pointer
  318. XR_valloc(/* unsigned ObjectSizeInbytes */);
  319. /* allocates an object of size at least ObjectSizeInbytes, whose
  320.    first address is at a system page boundary.  The object is also
  321.    made noncollectable, and can be made collectable by calling valloc_free.
  322.    The object is assumed to contain NO pointers, and is not cleared.
  323.    */
  324.  
  325. void
  326. XR_valloc_free(/* XR_Pointer ObjectAddress */);
  327. /* permits an object allocated by valloc to be collected if there
  328.    are no pointers to it.
  329.    */
  330.  
  331. void
  332. XR_make_uncollectable(/* XR_Pointer RealObjectAddress,
  333.                XR_Pointer AlternateAddressForRelease */);
  334. /* prevents the object pointed to by ObjectAddress from ever being collected. */
  335.  
  336. void
  337. XR_unmake_uncollectable(/* XR_Pointer ObjectAddress */);
  338. /* permits an object made uncollectable by a call on XR_make_uncollectable
  339.    to again enter the possible collection pool.  ObjectAddress can
  340.    be either the RealObjectAddress or the AlternateAddressForRelease give
  341.    to XR_make_uncollectable.
  342.    */
  343.  
  344.  
  345. /* The following routines are OBSOLETE.  They return pointers into the
  346.    middle of objects, leaving room for 8 byte headers.
  347.    */
  348.    
  349. XR_Pointer
  350. XR_calloc(/* unsigned ObjectCount, ObjectSizeInBytes */);
  351. /* allocates a new object of length at least ObjectCount * ObjectSizeInBytes.
  352.    The object is assumed to contain pointers, and is cleared to all zeros.
  353.    OBSOLETE */
  354.  
  355. XR_Pointer
  356. XR_clear_new(/* unsigned ObjectCount, ObjectSizeInBytes */);
  357. /* allocates a new object of length at least ObjectCount * ObjectSizeInBytes.
  358.    The object is assumed to contain pointers, and is cleared to all zeros.
  359.    OBSOLETE*/
  360.  
  361. XR_Pointer
  362. XR_new(/* unsigned ObjectSizeInBytes */);
  363. /* allocates a new object at least ObjectSizeInBytes.
  364.    The object is assumed to contain pointers, and is cleared to all zeros.
  365.    */
  366.  
  367. XR_Pointer
  368. XR_pointerfree_new(/* unsigned ObjectSizeInBytes */);
  369. /* allocates a new object at least ObjectSizeInBytes.
  370.    The object is assumed to contain NO pointers, and is not cleared.
  371.    OBSOLETE */
  372.  
  373. XR_Pointer
  374. XR_ralloc(/* unsigned ObjectSizeIn32BitWords */);
  375. /* allocates a new object of at least ObjectSizeIn32BitWords.
  376.    The object is assumed to contain NO pointers, and is not cleared.
  377.    OBSOLETE */
  378.    
  379. XR_Pointer
  380. XR_ralloc_comp(/* unsigned ObjectSizeIn32BitWords */);
  381. /* allocates a new object of at least ObjectSizeIn32BitWords.
  382.    The object is assumed to contain pointers, and is cleared to zeros.
  383.    OBSOLETE */
  384.  
  385. XR_Pointer
  386. XR_realloc(/* unsigned ObjectAddress; unsigned ObjectSizeInBytes */);
  387. /* allocates a new object of size at least ObjectSizeInBytes, and
  388.    copies the bytes at ObjectAddress into the new object.
  389.    ObjectSizeInBytes are always copied, so XR_realloc only makes
  390.    sense for growing, not shrinking, objects.  The object is assumed
  391.    to contain pointers, and any additional space is cleared to zeros.
  392.    OBSOLETE */
  393.  
  394. XR_Pointer
  395. XR_malloc(/* unsigned ObjectSizeInBytes */);
  396. /* allocates an object of size at least ObjectSizeInBytes, and
  397.    return the address.  The object is assumed to contain pointers,
  398.    and is cleared to zeros.
  399.    OBSOLETE */
  400.    
  401. void XR_unsafe_free(/* XR_Pointer */);
  402. /* Alias for XR_free. */
  403.    
  404. /* The following control routines are also OBSOLETE: */
  405. extern bool
  406. XR_GCGetMiserlyHeap(), XR_GCSetMiserlyHeap(/* bool */);
  407. /* Do nothing at the moment. Return FALSE */
  408.    
  409. /*
  410.  * Allocation and deallocation routines that traffic in uncollectable
  411.  * objects.  These were introduced as a patch to exisiting problems.
  412.  * They should be considered instantly OBSOLETE.
  413.  */
  414.  
  415. XR_Pointer 
  416. XR_UNCollect_malloc(/* long size */);
  417.  
  418. XR_Pointer
  419. XR_UNCollect_calloc(/* long size_elem, long num_elem */);
  420.  
  421. XR_Pointer
  422. XR_UNCollect_realloc(/* XR_Pointer old, long size */);
  423.  
  424. void
  425. XR_UNCollect_free(/* XR_Pointer ptr */);
  426.  
  427.  
  428. /***** Unix interface replacements (see Unix manuals). *****/
  429. /* All objects are assumed to possibly contain pointers, except valloc.
  430.    These are here for compatibility of pre-existing code, but for the
  431.    sake of clarity, because of slightly different semantics, it is
  432.    prefered to use the XR_foo name instead of just foo.
  433.     realloc
  434.     cfree
  435.     free
  436.     malloc
  437.     calloc 
  438.     valloc - special note: valloced objects in PCR are assumed to
  439.              contain no pointers, and are made not collectable.
  440.              valloc_free is available to make them collectable.
  441.    */
  442.  
  443.  
  444. /* Routines below are not for casual users */
  445.  
  446.  
  447. void
  448. XR_add_data_list(/* XR_Pointer startAddress, endAddress */);
  449. /* To be called by the initializing world to add a root.
  450.    Can be called at any time to add additional roots.
  451.    The words between startAddress and endAddress will be used as an
  452.    additional root set for garbage collections.  This is not for
  453.    casual use: only world initialization and dynamic loading ordinarly
  454.    use it.  The last word checked starts at endAddress-4.
  455.    */
  456.  
  457. typedef struct GC_InfoRep {
  458.     bool gci_full_collection;  /* This is a full collection */
  459.     /* More to come? */
  460. } * GC_Info;
  461.  
  462. typedef void (*RegisterGCCallbackType)(/* XR_Pointer clientdata,
  463.                       GC_Info info */);
  464.  
  465. void
  466. XR_RegisterGCCallBackBefore(/* RegisterGCCallbackType proc, XR_Pointer clientdata, RegisterGCCallbackType *oldproc, XR_Pointer *oldclientdata */);
  467.  
  468. void
  469. XR_RegisterGCCallBackAfter(/* RegisterGCCallbackType proc; XR_Pointer clientdata, RegisterGCCallbackType *oldproc; XR_Pointer *oldclientdata  */);
  470.  
  471. void
  472. XR_RegisterGCCallBackDuringInner(/* RegisterGCCallbackType proc; XR_Pointer clientdata, RegisterGCCallbackType *oldproc; XR_Pointer *oldclientdata  */); 
  473.  
  474. /* Registers subroutines to be called-back just before, and just after,
  475.    garbage collection.  These routines are not for casual use:  they
  476.    may be called inside the GC monitor lock, and so must not allocate
  477.    any storage.  Also, only one is kept, any new registration replaces
  478.    the old.  (The old proc and client data values are returned in the 
  479.    locations pointed to by oldproc and oldclientdata, unless these are null.)
  480.    Registering NIL turns off callback.  The call is made by the
  481.    GC daemon thread.  A failure to return promptly can be disastrous.
  482.    
  483.    The callback is made as:
  484.    (*proc)(clientdata, full_gc)
  485.    
  486.    For present purposes, a collection is defined to be occurring only
  487.    while the world is stopped.  The first two routines are called
  488.    just before and just after this occurs.  The fact that the collector
  489.    does much of its work concurrently is ignored.
  490.    A collection is defined to be full if no objects are preserved
  491.    simply because they survived some combination of previous collections.
  492.    
  493.    The routine XR_RegisterGCCallBackDuringInner expects to be called with
  494.    GC_allocate_ml already held.
  495.    The routine registered by XR_RegisterGCCallBackDuringInner is called 
  496.    with the world stopped, and with the allocate, virtual dirty bit,
  497.    and IOP order locks held.  It is called after all mark bits
  498.    have attained their final value.
  499.    */
  500.    
  501. typedef XR_Pointer (*GC_alloc_call_back_type)
  502.                      (/* long sz, bool is_atomic, XR_Pointer client_data */);
  503.    
  504. void GC_register_alloc_callback
  505.               (/* GC_alloc_call_back_type fn, XR_Pointer client_data,
  506.                   GC_alloc_call_back_type *Ofn, XR_Pointer *Oclient_data */);
  507. /* Register a routine to be called before every allocation.  If it returns 
  508.  * a non-NIL value, then that value is returned as the result of the
  509.  * allocator call.  Fn is run before the allocation monitor lock is acquired,
  510.  * but after acquiring a spearate monitor lock.  It should be safe to have
  511.  * fn unregister the callback (by passing 0 as the fn argument), and then
  512.  * recursively invoke the allocator.  A recursive invocation of the callback
  513.  * wwould result in deadlock.
  514.  * Client_data is passed to fn.  The old values of fn and client_data are
  515.  * returned in the third and fourth arguments.
  516.  * Most applications will want to have fn always return NIL.
  517.  */
  518.  
  519.  
  520.  
  521. void
  522. XR_SetupGC();
  523. /* Set up for garbage collection.  Called only by initializing world. */
  524.  
  525. void
  526. GC_register_displacement(/* unsigned DisplacementInBytes */);
  527. /* Register the given displacement as a valid displacement of a pointer
  528.    to an object into an object.  All values equal to an object address
  529.    plus the given displacement will henceforth be treated as pointers.
  530.    Ignored if the collector is not compiled to keep track of 
  531.    such things.  Calling this after allocation has taken place is more
  532.    expensive, but still safe.  We claim it is unreasonable to ever
  533.    unregister a displacement.  Thus there is no way to do it.
  534.    */
  535.  
  536.  
  537. #if defined(FINALIZE)
  538. /***** Finalization *****/
  539. /*
  540.   The finalization described here is the innermost level, and is not
  541.   indended for direct use.  Rather, language implementors are expected
  542.   to wrap their own layers around this.  For instance, there is a
  543.   different Cedar layer for use by Cedar/Mesa programmers.
  544.   */
  545.  
  546.  
  547. /*
  548.  * Finalizable Object structures and Finalization Queues:
  549.  *
  550.  * Invariants:
  551.  *
  552.  *   firstword, secondword - encode a pointer to an object
  553.  *     (a) disguised as pair < ptr&0xffff, (ptr>>16)&0xffff >
  554.  *       if it's finalizable
  555.  *     (b) undisguised as < ptr , nil > if it's not finalizable
  556.  *     N.B. since first 64K of address space isn't in heap, this
  557.  *       means (secondword == 0) iff the pointer is undisguised.
  558.  *   associatedFQ - pointer to a FinalizationQueueStructure
  559.  *     non-NIL iff the object is finalizable or on the finalization queue
  560.  *
  561.  * Thus, finalization states can be determined by:
  562.  *   enabled: (secondword != 0)
  563.  *   disabled: (associatedFQ == NIL)
  564.  *   onFQ: otherwise
  565.  */
  566.  
  567. typedef struct XR_FinalizationQueueStructure {
  568.     struct XR_FinalizableObjectStructure * head;
  569.     struct XR_FinalizableObjectStructure * tail;
  570.     struct XR_CVRep fqNonempty;
  571. } * XR_FinalizationQueue;
  572.  
  573. typedef struct XR_FinalizableObjectStructure {
  574.     unsigned long firstword;
  575.     unsigned long secondword;
  576.     XR_FinalizationQueue associatedFQ;
  577.     struct XR_FinalizableObjectStructure *next;
  578. } * XR_FinalizationHandle;
  579.  
  580. #define XR_IsDisguised(h) ((h)->secondword != 0)
  581.  
  582. #define XR_FetchFromDisguised(h) ( ((h)->firstword) | ((h)->secondword << 16) )
  583. #define XR_FetchFromUndisguised(h) ( (h)->firstword )
  584.  
  585. #define XR_StoreDisguised(w,h) { \
  586.     (h)->firstword = ((unsigned long)(w)) & 0xffff; \
  587.     (h)->secondword = (((unsigned long)(w)) >> 16) & 0xffff; \
  588.     }
  589. #define XR_StoreUndisguised(w,h) { \
  590.     (h)->firstword = ((unsigned long)(w)); \
  591.     (h)->secondword = 0; \
  592.     }
  593.  
  594. typedef enum {
  595.     fzsEnabled = 0,
  596.     fzsOnFQ = 1,
  597.     fzsDisabled = 2,
  598.     fzsError = 0x7fffffff    /* force to 32 bits */
  599. } XR_FinalizationState;
  600.  
  601.  
  602. XR_FinalizationQueue
  603. XR_NewFQ();
  604. /* return a new, empty, initialized finalization queue. */
  605.  
  606. XR_FinalizationHandle
  607. XR_FQNextNoAbort(/* XR_FinalizationQueue fq */);
  608. /* return the next handle on queue 'fq', waiting on a condition variable
  609.    until there is an item if necessary.  If there is no item, or the
  610.    wait is interrupted, return NIL */
  611.  
  612. bool
  613. XR_FQEmpty(/* XR_FinalizationQueue fq */);
  614.  
  615. XR_FinalizationHandle
  616. XR_NewFinalizationHandle();
  617. /* return a new, empty, initialized handle for an object to be finalized. */
  618.  
  619. void
  620. XR_EnableFinalization(/* XR_Pointer object;
  621.              XR_FinalizationQueue fq;
  622.              XR_FinalizationHandle h */);
  623. /* Cause the object to be enabled for finalization.  
  624.    'h' is updated to describe the object.  When the time comes,
  625.    fq will be the finalization queue on which the object is placed.  
  626.    */
  627.  
  628.  
  629. XR_FinalizationState
  630. XR_DisableFinalization(/* XR_FinalizationHandle h */);
  631. /* Disable the object described by 'h' for finalization.  Return its
  632.    prior XR_FinalizationState.  If it is already on a finalize q, remote it.
  633.    */
  634.  
  635. XR_FinalizationState
  636. XR_ReenableFinalization(/* XR_FinalizationHandle h;
  637.                XR_FinalizationQueue fq */);
  638. /* Causes an object which was once finalizable to be so again, now
  639.    on queue 'fq'.  If it is on some other queue, it is removed first.
  640.    Prior state is returned.
  641.    */
  642.  
  643. XR_FinalizationState
  644. XR_GetFinalizationState(/* XR_FinalizationHandle h */);
  645. /* get the finalization state of the object */
  646.  
  647. XR_Pointer
  648. XR_HandleToObject(/* XR_FinalizationHandle h */);
  649. /* Get the pointer to the real object, given its handle */
  650.  
  651. #endif /* FINALIZE */
  652.  
  653. #endif /* _XR_GC_ */
  654.